import subprocess
import docx2pdf
from concurrent.futures import ThreadPoolExecutor
import os
import logging

# 配置logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')

def convert_doc_to_docx(input_doc, output_docx):
    """将DOC文件转换为DOCX文件"""
    try:
        subprocess.run(['unoconv', '-f', 'docx', '-o', output_docx, input_doc], check=True)
        logging.info(f"成功将 {input_doc} 转换为 {output_docx}")
        return True
    except subprocess.CalledProcessError as e:
        logging.error(f"将 {input_doc} 转换为 {output_docx} 时出错: {e}")
        return False

def convert_docx_to_pdf(input_docx, output_pdf):
    """将DOCX文件转换为PDF文件"""
    try:
        docx2pdf.convert(input_docx, output_pdf)
        logging.info(f"成功将 {input_docx} 转换为 {output_pdf}")
        return True
    except Exception as e:
        logging.error(f"将 {input_docx} 转换为 {output_pdf} 时出错: {e}")
        return False


def batch_convert_to_pdf(input_dir, output_dir_docx, output_dir_pdf):
    """批量转换文件夹中的所有DOC和DOCX文件到PDF"""
    # 确保输出目录存在
    os.makedirs(output_dir_docx, exist_ok=True)
    os.makedirs(output_dir_pdf, exist_ok=True)
    # 遍历输入目录中的所有文件
    for filename in os.listdir(input_dir):
        input_path = os.path.join(input_dir, filename)
        base_filename = os.path.splitext(filename)[0]
        output_pdf_path = os.path.join(output_dir_pdf, f"{base_filename}.pdf")
        
        if filename.lower().endswith('.docx'):
            # 直接转换为PDF
            convert_docx_to_pdf(input_path, output_pdf_path)
        elif filename.lower().endswith('.doc'):
            # 先转换为DOCX
            output_docx_path = os.path.join(output_dir_pdf, f"{base_filename}.docx")
            if convert_doc_to_docx(input_path, output_docx_path):
                # 然后转换为PDF
                convert_docx_to_pdf(output_docx_path, output_pdf_path)
        else:
            # 不是DOC或DOCX文件，报错
            logging.error(f"Unsupported file format: {filename}")
        

def process_doc_file(input_path, output_docx_path, output_pdf_path):
    """处理 .doc 文件：先转换为 .docx，再转换为 .pdf"""
    return convert_doc_to_docx(input_path, output_docx_path) and convert_docx_to_pdf(output_docx_path, output_pdf_path)


def process_docx_file(input_path, output_pdf_path):
    """处理 .docx 文件：直接转换为 .pdf"""
    return convert_docx_to_pdf(input_path, output_pdf_path)


def batch_convert_parallel(input_dir, output_dir_docx, output_dir_pdf, max_workers=None):
    os.makedirs(output_dir_docx, exist_ok=True)
    os.makedirs(output_dir_pdf, exist_ok=True)

    doc_files = [f for f in os.listdir(input_dir) if f.lower().endswith('.doc')]
    docx_files = [f for f in os.listdir(input_dir) if f.lower().endswith('.docx')]

    max_workers = max_workers or min(32, os.cpu_count() + 4)

    with ThreadPoolExecutor(max_workers=max_workers) as executor:
        futures = []

        # 提交 .doc 文件任务
        for filename in doc_files:
            input_path = os.path.join(input_dir, filename)
            output_docx_path = os.path.join(output_dir_docx, f"{os.path.splitext(filename)[0]}.docx")
            output_pdf_path = os.path.join(output_dir_pdf, f"{os.path.splitext(filename)[0]}.pdf")
            futures.append(executor.submit(process_doc_file, input_path, output_docx_path, output_pdf_path))

        # 提交 .docx 文件任务
        for filename in docx_files:
            input_path = os.path.join(input_dir, filename)
            output_pdf_path = os.path.join(output_dir_pdf, f"{os.path.splitext(filename)[0]}.pdf")
            futures.append(executor.submit(process_docx_file, input_path, output_pdf_path))

        # 等待所有任务完成
        for future in futures:
            if not future.result():
                logging.error("有一个或多个文件转换失败")


# 注意：在使用线程池时，lambda函数需要显式地接受参数，否则会引发异常。

# 示例用法
if __name__ == "__main__":
    input_dir = "input_docs"       # 输入目录，包含所有需要转换的DOC文件
    output_dir_docx = "output_docx" # 中间输出目录，存储转换后的DOCX文件
    output_dir_pdf = "output_pdf"   # 最终输出目录，存储转换后的PDF文件
    
    batch_convert_to_pdf(input_dir, output_dir_docx, output_dir_pdf)
